// utils/performance.js
/**
 * 性能优化工具模块
 * 提供加载状态管理、错误处理、缓存等功能
 */

/**
 * 加载状态管理器
 */
const LoadingManager = {
  // 活动的加载状态记录
  activeLoadings: new Set(),
  
  /**
   * 显示加载状态
   * @param {string} key 加载状态标识
   * @param {object} options 加载选项
   */
  show(key, options = {}) {
    const {
      title = '加载中...',
      mask = true,
      duration = 0
    } = options
    
    this.activeLoadings.add(key)
    
    wx.showLoading({
      title,
      mask
    })
    
    // 如果设置了持续时间，自动隐藏
    if (duration > 0) {
      setTimeout(() => {
        this.hide(key)
      }, duration)
    }
  },
  
  /**
   * 隐藏加载状态
   * @param {string} key 加载状态标识
   */
  hide(key) {
    this.activeLoadings.delete(key)
    
    // 只有当没有其他加载状态时才隐藏
    if (this.activeLoadings.size === 0) {
      wx.hideLoading()
    }
  },
  
  /**
   * 隐藏所有加载状态
   */
  hideAll() {
    this.activeLoadings.clear()
    wx.hideLoading()
  },
  
  /**
   * 检查是否有活动的加载状态
   * @returns {boolean}
   */
  hasActive() {
    return this.activeLoadings.size > 0
  }
}

/**
 * 增强的错误处理器
 */
const ErrorHandler = {
  // 错误类型定义
  ERROR_TYPES: {
    NETWORK: 'network',
    API: 'api',
    VALIDATION: 'validation',
    PERMISSION: 'permission',
    TIMEOUT: 'timeout',
    UNKNOWN: 'unknown'
  },
  
  /**
   * 处理错误
   * @param {Error|object} error 错误对象
   * @param {object} context 上下文信息
   */
  handle(error, context = {}) {
    const errorInfo = this.parseError(error)
    
    // 记录错误日志
    this.logError(errorInfo, context)
    
    // 显示用户友好的错误信息
    this.showUserFriendlyError(errorInfo)
    
    // 上报错误到服务端
    this.reportError(errorInfo, context)
    
    return errorInfo
  },
  
  /**
   * 解析错误信息
   * @param {Error|object} error 错误对象
   * @returns {object} 解析后的错误信息
   */
  parseError(error) {
    if (!error) {
      return {
        type: this.ERROR_TYPES.UNKNOWN,
        message: '未知错误',
        code: 'UNKNOWN_ERROR'
      }
    }
    
    // 网络错误
    if (error.errMsg && error.errMsg.includes('request:fail')) {
      return {
        type: this.ERROR_TYPES.NETWORK,
        message: '网络连接失败，请检查网络设置',
        code: 'NETWORK_ERROR',
        originalError: error
      }
    }
    
    // API错误
    if (error.statusCode) {
      return {
        type: this.ERROR_TYPES.API,
        message: this.getApiErrorMessage(error.statusCode),
        code: `API_ERROR_${error.statusCode}`,
        statusCode: error.statusCode,
        originalError: error
      }
    }
    
    // 权限错误
    if (error.errMsg && error.errMsg.includes('auth')) {
      return {
        type: this.ERROR_TYPES.PERMISSION,
        message: '权限不足，请检查相关授权',
        code: 'PERMISSION_ERROR',
        originalError: error
      }
    }
    
    // 超时错误
    if (error.errMsg && error.errMsg.includes('timeout')) {
      return {
        type: this.ERROR_TYPES.TIMEOUT,
        message: '请求超时，请重试',
        code: 'TIMEOUT_ERROR',
        originalError: error
      }
    }
    
    // 默认错误
    return {
      type: this.ERROR_TYPES.UNKNOWN,
      message: error.message || error.errMsg || '操作失败，请重试',
      code: error.code || 'GENERIC_ERROR',
      originalError: error
    }
  },
  
  /**
   * 获取API错误信息
   * @param {number} statusCode HTTP状态码
   * @returns {string} 错误信息
   */
  getApiErrorMessage(statusCode) {
    const errorMessages = {
      400: '请求参数错误',
      401: '身份验证失败，请重新登录',
      403: '权限不足',
      404: '请求的资源不存在',
      500: '服务器内部错误',
      502: '网关错误',
      503: '服务暂时不可用',
      504: '网关超时'
    }
    
    return errorMessages[statusCode] || `服务器错误 (${statusCode})`
  },
  
  /**
   * 显示用户友好的错误信息
   * @param {object} errorInfo 错误信息
   */
  showUserFriendlyError(errorInfo) {
    const { message, type } = errorInfo
    
    switch (type) {
      case this.ERROR_TYPES.NETWORK:
        wx.showModal({
          title: '网络错误',
          content: message,
          showCancel: false,
          confirmText: '我知道了'
        })
        break
        
      case this.ERROR_TYPES.PERMISSION:
        wx.showModal({
          title: '权限提醒',
          content: message,
          confirmText: '去设置',
          cancelText: '取消',
          success: (res) => {
            if (res.confirm) {
              wx.openSetting()
            }
          }
        })
        break
        
      default:
        wx.showToast({
          title: message,
          icon: 'none',
          duration: 3000
        })
    }
  },
  
  /**
   * 记录错误日志
   * @param {object} errorInfo 错误信息
   * @param {object} context 上下文信息
   */
  logError(errorInfo, context) {
    const logData = {
      timestamp: new Date().toISOString(),
      error: errorInfo,
      context,
      userAgent: wx.getSystemInfoSync(),
      page: getCurrentPages()[getCurrentPages().length - 1]?.route || 'unknown'
    }
    
    console.error('应用错误:', logData)
    
    // 存储到本地，用于后续上报
    try {
      const logs = wx.getStorageSync('error_logs') || []
      logs.push(logData)
      
      // 只保留最近100条日志
      if (logs.length > 100) {
        logs.splice(0, logs.length - 100)
      }
      
      wx.setStorageSync('error_logs', logs)
    } catch (e) {
      console.error('保存错误日志失败:', e)
    }
  },
  
  /**
   * 上报错误到服务端
   * @param {object} errorInfo 错误信息
   * @param {object} context 上下文信息
   */
  reportError(errorInfo, context) {
    // 延迟上报，避免影响用户体验
    setTimeout(() => {
      try {
        wx.request({
          url: 'https://api.example.com/error-report',
          method: 'POST',
          data: {
            error: errorInfo,
            context,
            timestamp: new Date().toISOString(),
            systemInfo: wx.getSystemInfoSync()
          },
          fail: (err) => {
            console.error('错误上报失败:', err)
          }
        })
      } catch (e) {
        console.error('错误上报异常:', e)
      }
    }, 1000)
  }
}

/**
 * 缓存管理器
 */
const CacheManager = {
  // 缓存配置
  CACHE_CONFIG: {
    USER_PROFILE: { key: 'user_profile', ttl: 30 * 60 * 1000 }, // 30分钟
    DISCOVERY_LIST: { key: 'discovery_list', ttl: 5 * 60 * 1000 }, // 5分钟
    MATCHES_LIST: { key: 'matches_list', ttl: 10 * 60 * 1000 }, // 10分钟
    COMMUNITY_POSTS: { key: 'community_posts', ttl: 5 * 60 * 1000 }, // 5分钟
    SYSTEM_CONFIG: { key: 'system_config', ttl: 60 * 60 * 1000 } // 1小时
  },
  
  /**
   * 设置缓存
   * @param {string} configKey 缓存配置键
   * @param {any} data 缓存数据
   * @param {number} customTtl 自定义过期时间
   */
  set(configKey, data, customTtl = null) {
    try {
      const config = this.CACHE_CONFIG[configKey]
      if (!config) {
        console.error('未找到缓存配置:', configKey)
        return false
      }
      
      const ttl = customTtl || config.ttl
      const cacheData = {
        data,
        timestamp: Date.now(),
        ttl
      }
      
      wx.setStorageSync(config.key, cacheData)
      return true
    } catch (error) {
      console.error('设置缓存失败:', error)
      return false
    }
  },
  
  /**
   * 获取缓存
   * @param {string} configKey 缓存配置键
   * @returns {any} 缓存数据，如果过期或不存在则返回null
   */
  get(configKey) {
    try {
      const config = this.CACHE_CONFIG[configKey]
      if (!config) {
        console.error('未找到缓存配置:', configKey)
        return null
      }
      
      const cacheData = wx.getStorageSync(config.key)
      if (!cacheData) return null
      
      const { data, timestamp, ttl } = cacheData
      const now = Date.now()
      
      // 检查是否过期
      if (now - timestamp > ttl) {
        this.remove(configKey)
        return null
      }
      
      return data
    } catch (error) {
      console.error('获取缓存失败:', error)
      return null
    }
  },
  
  /**
   * 移除缓存
   * @param {string} configKey 缓存配置键
   */
  remove(configKey) {
    try {
      const config = this.CACHE_CONFIG[configKey]
      if (config) {
        wx.removeStorageSync(config.key)
      }
    } catch (error) {
      console.error('移除缓存失败:', error)
    }
  },
  
  /**
   * 清除所有缓存
   */
  clearAll() {
    try {
      Object.values(this.CACHE_CONFIG).forEach(config => {
        wx.removeStorageSync(config.key)
      })
    } catch (error) {
      console.error('清除缓存失败:', error)
    }
  },
  
  /**
   * 获取缓存大小信息
   * @returns {object} 缓存大小信息
   */
  getCacheSize() {
    try {
      const info = wx.getStorageInfoSync()
      return {
        keys: info.keys,
        currentSize: info.currentSize,
        limitSize: info.limitSize
      }
    } catch (error) {
      console.error('获取缓存大小失败:', error)
      return { keys: [], currentSize: 0, limitSize: 0 }
    }
  }
}

/**
 * 性能监控器
 */
const PerformanceMonitor = {
  // 性能数据
  performanceData: {
    pageLoadTimes: {},
    apiResponseTimes: {},
    memoryUsage: []
  },
  
  /**
   * 开始监控页面加载
   * @param {string} pagePath 页面路径
   */
  startPageLoad(pagePath) {
    this.performanceData.pageLoadTimes[pagePath] = {
      startTime: Date.now()
    }
  },
  
  /**
   * 结束监控页面加载
   * @param {string} pagePath 页面路径
   */
  endPageLoad(pagePath) {
    const pageData = this.performanceData.pageLoadTimes[pagePath]
    if (pageData && pageData.startTime) {
      pageData.endTime = Date.now()
      pageData.duration = pageData.endTime - pageData.startTime
      
      console.log(`页面 ${pagePath} 加载时间: ${pageData.duration}ms`)
      
      // 如果加载时间过长，记录警告
      if (pageData.duration > 3000) {
        console.warn(`页面 ${pagePath} 加载时间过长: ${pageData.duration}ms`)
      }
    }
  },
  
  /**
   * 监控API响应时间
   * @param {string} apiPath API路径
   * @param {number} startTime 开始时间
   * @param {number} endTime 结束时间
   */
  recordApiResponse(apiPath, startTime, endTime) {
    const duration = endTime - startTime
    
    if (!this.performanceData.apiResponseTimes[apiPath]) {
      this.performanceData.apiResponseTimes[apiPath] = []
    }
    
    this.performanceData.apiResponseTimes[apiPath].push({
      timestamp: Date.now(),
      duration
    })
    
    console.log(`API ${apiPath} 响应时间: ${duration}ms`)
    
    // 如果响应时间过长，记录警告
    if (duration > 5000) {
      console.warn(`API ${apiPath} 响应时间过长: ${duration}ms`)
    }
    
    // 只保留最近50条记录
    if (this.performanceData.apiResponseTimes[apiPath].length > 50) {
      this.performanceData.apiResponseTimes[apiPath].shift()
    }
  },
  
  /**
   * 记录内存使用情况
   */
  recordMemoryUsage() {
    try {
      const pages = getCurrentPages()
      const memoryInfo = {
        timestamp: Date.now(),
        pageCount: pages.length,
        currentPage: pages[pages.length - 1]?.route || 'unknown'
      }
      
      this.performanceData.memoryUsage.push(memoryInfo)
      
      // 只保留最近100条记录
      if (this.performanceData.memoryUsage.length > 100) {
        this.performanceData.memoryUsage.shift()
      }
      
      // 如果页面栈过深，发出警告
      if (pages.length > 10) {
        console.warn(`页面栈过深: ${pages.length} 层`)
      }
    } catch (error) {
      console.error('记录内存使用失败:', error)
    }
  },
  
  /**
   * 获取性能报告
   * @returns {object} 性能报告
   */
  getPerformanceReport() {
    const report = {
      pageLoadTimes: {},
      apiResponseTimes: {},
      averageLoadTime: 0,
      averageApiTime: 0,
      memoryPeakUsage: 0
    }
    
    // 计算页面平均加载时间
    const pageLoadData = this.performanceData.pageLoadTimes
    let totalLoadTime = 0
    let loadCount = 0
    
    Object.keys(pageLoadData).forEach(page => {
      const data = pageLoadData[page]
      if (data.duration) {
        report.pageLoadTimes[page] = data.duration
        totalLoadTime += data.duration
        loadCount++
      }
    })
    
    if (loadCount > 0) {
      report.averageLoadTime = Math.round(totalLoadTime / loadCount)
    }
    
    // 计算API平均响应时间
    const apiData = this.performanceData.apiResponseTimes
    let totalApiTime = 0
    let apiCount = 0
    
    Object.keys(apiData).forEach(api => {
      const responses = apiData[api]
      if (responses.length > 0) {
        const avgTime = responses.reduce((sum, item) => sum + item.duration, 0) / responses.length
        report.apiResponseTimes[api] = Math.round(avgTime)
        totalApiTime += avgTime
        apiCount++
      }
    })
    
    if (apiCount > 0) {
      report.averageApiTime = Math.round(totalApiTime / apiCount)
    }
    
    // 计算内存峰值使用
    const memoryData = this.performanceData.memoryUsage
    report.memoryPeakUsage = Math.max(...memoryData.map(item => item.pageCount), 0)
    
    return report
  }
}

/**
 * 图片加载优化器
 */
const ImageOptimizer = {
  // 图片缓存
  imageCache: new Map(),
  
  /**
   * 预加载图片
   * @param {array} imageUrls 图片URL数组
   * @returns {Promise} 预加载Promise
   */
  preloadImages(imageUrls) {
    if (!Array.isArray(imageUrls)) return Promise.resolve()
    
    const promises = imageUrls.map(url => this.preloadSingleImage(url))
    return Promise.allSettled(promises)
  },
  
  /**
   * 预加载单张图片
   * @param {string} imageUrl 图片URL
   * @returns {Promise} 预加载Promise
   */
  preloadSingleImage(imageUrl) {
    return new Promise((resolve, reject) => {
      if (this.imageCache.has(imageUrl)) {
        resolve(imageUrl)
        return
      }
      
      wx.getImageInfo({
        src: imageUrl,
        success: (res) => {
          this.imageCache.set(imageUrl, {
            width: res.width,
            height: res.height,
            path: res.path,
            timestamp: Date.now()
          })
          resolve(res)
        },
        fail: (error) => {
          console.error('图片预加载失败:', imageUrl, error)
          reject(error)
        }
      })
    })
  },
  
  /**
   * 获取优化的图片URL
   * @param {string} originalUrl 原始URL
   * @param {object} options 优化选项
   * @returns {string} 优化后的URL
   */
  getOptimizedImageUrl(originalUrl, options = {}) {
    if (!originalUrl) return ''
    
    const {
      width = 0,
      height = 0,
      quality = 80,
      format = 'webp'
    } = options
    
    // 如果是本地图片，直接返回
    if (originalUrl.startsWith('/') || originalUrl.startsWith('data:')) {
      return originalUrl
    }
    
    // 构建优化参数
    const params = []
    if (width > 0) params.push(`w_${width}`)
    if (height > 0) params.push(`h_${height}`)
    if (quality < 100) params.push(`q_${quality}`)
    if (format !== 'original') params.push(`f_${format}`)
    
    if (params.length === 0) return originalUrl
    
    // 假设使用CDN图片处理服务
    const separator = originalUrl.includes('?') ? '&' : '?'
    return `${originalUrl}${separator}${params.join(',')}`
  },
  
  /**
   * 清理图片缓存
   * @param {number} maxAge 最大缓存时间（毫秒）
   */
  cleanImageCache(maxAge = 30 * 60 * 1000) {
    const now = Date.now()
    
    for (const [url, data] of this.imageCache.entries()) {
      if (now - data.timestamp > maxAge) {
        this.imageCache.delete(url)
      }
    }
  }
}

module.exports = {
  LoadingManager,
  ErrorHandler,
  CacheManager,
  PerformanceMonitor,
  ImageOptimizer
}